﻿//  --------------------------------
//  Copyright (c) AW Systems, Inc. All rights reserved.
//  This source code is made available under the terms of the Microsoft Public License (Ms-PL)
//  http://www.codeplex.com/SLAM/license
//  ---------------------------------

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Text;
using AWS.SLAM;
using AWS.SLAM.Configuration;
using StructureMap;
using StructureMap.Pipeline;
using StructureMap.Configuration.DSL;
using StructureMap.Attributes;
using System.Xml;
using System.Xml.Linq;
using Microsoft.SharePoint;

namespace AWS.SLAM.StructureMap
{
    public class ComponentFactory : IComponentFactory
    {
        private static bool configured = false;

        public ComponentFactory()
        {
            Initialize();
        }

        private void Initialize()
        {
            if (!configured)
            {
                //Register defaults
                SLAMRegistry registry = new SLAMRegistry();
                ObjectFactory.Initialize(
                    container =>
                    {
                        container.AddRegistry(registry);
                    });

                //Register default Profiles
                DefaultContentTypeProfile contentTypeProfile = new DefaultContentTypeProfile();
                contentTypeProfile.CreateProfile(registry, "DefaultContentType");

                DefaultListTypeProfile listProfile = new DefaultListTypeProfile();
                listProfile.CreateProfile(registry, "DefaultList");

                //Register custom Profiles
                IConfigurationManager configuration = ObjectFactory.GetInstance<IConfigurationManager>();
                configuration.RegisterSection("TypeProfiles",
                    config =>
                    {
                        object section = null;
                        if (config is XDocument)
                        {
                            section = new XmlTypeProfileSection((XDocument)config);
                        }
                        return section;
                    });

                XmlTypeProfileSection profileSection = configuration.GetSection<XmlTypeProfileSection>("TypeProfiles");

                foreach (CustomTypeProfile typeProfile in profileSection.GetCustomTypeProfiles())
                {
                    try
                    {
                        ITypeProfile profileObject = Activator.CreateInstance(Type.GetType(typeProfile.AssemblyQualifiedTypeName)) as ITypeProfile;
                        if (profileObject != null)
                        {
                            profileObject.CreateProfile(registry, typeProfile.Name);
                        }
                    }
                    catch 
                    {
                        throw new Exception("Unable to load assembly for Type Profile: " + typeProfile.Name + ", " + typeProfile.AssemblyQualifiedTypeName);
                    }
                }

                //Reset Plugin Graph
                ObjectFactory.Initialize(
                    container =>
                    {
                        container.AddRegistry(registry);
                    });

                //Get the instance again
                configuration = ObjectFactory.GetInstance<IConfigurationManager>();
                configuration.RegisterSection("TypeProfiles",
                    config =>
                    {
                        object section = null;
                        if (config is XDocument)
                        {
                            section = new XmlTypeProfileSection((XDocument)config);
                        }
                        return section;
                    });
                configured = true;
            }
        }

        #region IComponentFactory Members

        public T GetInstance<T>()
        {
            return ObjectFactory.GetInstance<T>();
        }

        public T GetInstance<T>(string siteCollection, string site, string typeName)
        {
            IConfigurationManager configuration = ObjectFactory.GetInstance<IConfigurationManager>();
            XmlTypeProfileSection profileSection = configuration.GetSection<XmlTypeProfileSection>("TypeProfiles");
            ObjectFactory.Profile = profileSection.GetTypeProfileName(siteCollection, site, "", typeName);
            return ObjectFactory.GetInstance<T>();
        }

        public T GetInstance<T>(string siteCollection, string site, string id, string typeName)
        {
            IConfigurationManager configuration = ObjectFactory.GetInstance<IConfigurationManager>();
            XmlTypeProfileSection profileSection = configuration.GetSection<XmlTypeProfileSection>("TypeProfiles");
            ObjectFactory.Profile = profileSection.GetTypeProfileName(siteCollection, site, id, typeName);
            return ObjectFactory.GetInstance<T>();
        }

        public void ResetContainer()
        {
            configured = false;
            Initialize();
        }

        #endregion
    }
}
